home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue37 / D4Bugs / FixupLB.pas next >
Encoding:
Pascal/Delphi Source File  |  1998-07-27  |  3.2 KB  |  118 lines

  1. unit FixupLB;
  2.  
  3. // Simple unit that patches the StdCtrls.TCustomListBox.GetItemIndex
  4. // method in Delphi 4.0 (build 5.37)
  5. //
  6. // July 1998, by Hallvard Vassbotn (hallvard@falcon.no)
  7.  
  8. interface
  9.  
  10. implementation
  11.  
  12. uses
  13.   Windows,
  14.   TypInfo,
  15.   StdCtrls;
  16.  
  17. type
  18.   PPGetItemIndex = ^PGetItemIndex;
  19.   PGetItemIndex = ^TGetItemIndex;
  20.   TGetItemIndex = packed record
  21.     PUSH_EBX      :  byte;
  22.     MOV_EBX_EAX   : word;
  23.     CMP_BYTE_PTR  : word;
  24.     ADDR_Offset   : Cardinal;
  25.     False_ZERO    : byte;
  26.     JNZ           : byte;
  27.     ELSE_REL_ADDR : byte;
  28.     PUSH_LParam   : word;
  29.     PUSH_WParam   : word;
  30.     PUSH_Msg      : byte;
  31.     Msg_Const     : Cardinal;
  32.     MOV_EAX_EBX   : word;
  33.     CALL          : byte;
  34.   end;
  35.   PGetItemIndexInPackage = ^TGetItemIndexInPackage;
  36.   TGetItemIndexInPackage = packed record
  37.     JMP_DWORD: word;
  38.     ActualGetItemIndex : PPGetItemIndex;
  39.   end;
  40.   TBytes = array[0..3] of byte;
  41.  
  42. const
  43.   OpCode_JNZ       = $75;
  44.   OpCode_JZ        = $74;
  45.   OpCode_JMP_DWORD = $25FF;
  46.  
  47. function IsBuggyCode(var GetItemIndex: PGetItemIndex): boolean;
  48. var
  49.   GetItemIndexInPackage: PGetItemIndexInPackage absolute GetItemIndex;
  50. begin
  51.   // Verify that this is a static method
  52.   Result := (TBytes(GetItemIndex)[3] < $FE);
  53.   if Result then
  54.   begin
  55.     // Handle the case when TCustomList.GetItemIndex is in a package
  56.     if (GetItemIndexInPackage^.JMP_DWORD = OpCode_JMP_DWORD) then
  57.       GetItemIndex := GetItemIndexInPackage^.ActualGetItemIndex^;
  58.  
  59.     with GetItemIndex^ do
  60.     begin
  61.       Result :=
  62.         // The buggy instruction, should have been OpCode_JZ
  63.         (JNZ = OpCode_JNZ)     and
  64.         // Check the other instructions as well, just to be sure
  65.         (PUSH_EBX     = $53)   and
  66.         (MOV_EBX_EAX  = $D88B) and
  67.         (CMP_BYTE_PTR = $BB80) and
  68.         (False_ZERO   = $00)   and
  69.         (ELSE_REL_ADDR= $18)   and
  70.         (PUSH_LParam  = $006A) and
  71.         (PUSH_WParam  = $006A) and
  72.         (PUSH_Msg     = $68)   and
  73.         (Msg_Const    = $19f)  and
  74.         (MOV_EAX_EBX  = $C38B) and
  75.         (CALL         = $E8)   ;
  76.     end;
  77.   end;
  78. end;
  79.  
  80. procedure WriteCodeByte(CodeAddress: pointer; Value: byte);
  81. var
  82.   WrittenBytes: Cardinal;
  83. begin
  84.   // Must use WriteProcessMemory or VirtualProtect to write to code segment
  85.   WriteProcessMemory(GetCurrentProcess, CodeAddress, @Value, SizeOf(Value), WrittenBytes);
  86. end;
  87.  
  88. type
  89.   // Publish ItemIndex to easily get address of GetItemIndex method
  90.   TPublishedListBox = class(TCustomListBox)
  91.   published
  92.     property ItemIndex;
  93.   end;
  94.  
  95. procedure Fix_TCustomListBox_GetItemIndex_Bug;
  96. var
  97.   PropInfo    : PPropInfo;
  98.   GetItemIndex: PGetItemIndex;
  99. begin
  100.   // Get the property information for the newly published ItemIndex property
  101.   PropInfo := TypInfo.GetPropInfo(TPublishedListBox.ClassInfo, 'ItemIndex');
  102.   if Assigned(PropInfo) then
  103.   begin
  104.     // Get the get-property method address
  105.     GetItemIndex := PropInfo^.GetProc;
  106.  
  107.     // Now check that the buggy code is there
  108.     if IsBuggyCode(GetItemIndex) then
  109.       // Patch in the correction, voilα!
  110.       // Same as GetItemIndex^.JNZ := OpCode_JZ, without the AV...
  111.       WriteCodeByte(@GetItemIndex^.JNZ, OpCode_JZ);
  112.   end;
  113. end;
  114.  
  115. initialization
  116.   Fix_TCustomListBox_GetItemIndex_Bug;
  117. end.
  118.